VFG.CalculatorBillboard = function(viewer,options) {
	this.option = Cesium.defaultValue(options, Cesium.defaultValue.EMPTY_OBJECT);
	this.viewer = Cesium.defaultValue(viewer, undefined);
	this.options = options;
	this.parentId= options.parentId||'';
	this.id= options.id;
	this.name= options.name||'';
	this.code= options.code||'';
	this.type= options.type||'';
	this.position=options.position||null;
	this.orientation=options.orientation||{};
	this.model=options.thing||{};
	this.attribute=options.attribute||{};
	this.propertys=options.propertys||[];
	this.videoEle=options.videoEle||null;
	this.isCreateVideoEle=false;
	
	this.primitive;
	this.vertices=[];
	this.normals=[];
	this.colors=[];
	this.uvs=[];
	
	this.geometry={
		vertices: [],
		normals: [],
		colors: [],
		uvs: [],
		indices:[],
	}
	this.init();
}

VFG.CalculatorBillboard.prototype.init=function(){
	this.read();
}

/**
 * read
 */
VFG.CalculatorBillboard.prototype.read=function(){
	var _this=this;
	var request = new XMLHttpRequest();
	request.onreadystatechange = function() {
		if (request.readyState == 4 && request.status != 404) {
			try{
				_this.parse(request.responseText);
				_this.create(_this.geometry);
				if(_this.success){
					_this.success(_this);
				}
				if(_this.complete){
					_this.complete();
				}
			}catch (e) {
				if(_this.error){
					_this.error(e);
				}
				if(_this.complete){
					_this.complete();
				}
			}
		}
	};
	request.onerror=function(error){
		if(_this.error){
			_this.error(error);
		}
		if(_this.complete){
			_this.complete();
		}
	};
	request.ontimeout=function(error){
		if(_this.error){
			_this.error('加载超时！');
		}
		if(_this.complete){
			_this.complete();
		}
	};
	request.open('GET', _this.model.url, true); 
	request.send();
	if(_this.complete){
		_this.complete();
	}
}

/**
 * 创建图元
 */
VFG.CalculatorBillboard.prototype.create=function(geometry){
	var _this=this;
	var normals=geometry.normals;
	var uvs=geometry.uvs;
	var vertices=geometry.vertices;
	var indices=new Uint16Array(geometry.indices);
	
/*	this._primitiveYZ=new Cesium.Primitive({
        geometryInstances : new Cesium.GeometryInstance({
            geometry : new Cesium.PlaneGeometry({
                vertexFormat : Cesium.PerInstanceColorAppearance.VERTEX_FORMAT,
            }),
            modelMatrix : this.getModelMatrixYZ(),
            id:_this.id+"-YZ",
            pickPrimitive : this,
            attributes : {
                color : new Cesium.ColorGeometryInstanceAttribute(1.0, 0.0, 0.0, 0.3)
            }
        }),
        appearance : new Cesium.PerInstanceColorAppearance({
            closed: false,
            translucent: false
        })
    })*/

	
	
    this.primitive=_this.viewer.scene.primitives.add(new Cesium.Primitive({
        geometryInstances: new Cesium.GeometryInstance({
            geometry: new Cesium.Geometry({
                attributes: {
                    position: new Cesium.GeometryAttribute({
                        componentDatatype: Cesium.ComponentDatatype.DOUBLE,
                        componentsPerAttribute: 3,
                        values: vertices
                    }),
                    normal: new Cesium.GeometryAttribute({
                        componentDatatype: Cesium.ComponentDatatype.FLOAT,
                        componentsPerAttribute: 3,
                        values: normals
                    }),
                    st: new Cesium.GeometryAttribute({
                        componentDatatype: Cesium.ComponentDatatype.FLOAT,
                        componentsPerAttribute: 2,
                        values: uvs
                    }),
                },
               // indices: indices, 
                pickPrimitive : this,
                primitiveType: Cesium.PrimitiveType.TRIANGLES,
                boundingSphere: Cesium.BoundingSphere.fromVertices(vertices),
            }),
            id : _this.id,
            modelMatrix: _this.getMatrix(),
        }),
       appearance: new Cesium.MaterialAppearance({
    	    material: _this.getMaterial(),
            faceForward : true, 
            closed: false 
        }),
        asynchronous: false
    }));
}

VFG.CalculatorBillboard.prototype.getMaterial = function() {
	var _self = this;
	if(_self.videoEle){
		_self.canplaythrough=function () {
	    	_self.viewer.clock.onTick.addEventListener(_self.activeVideoListener, _self);
	    };
	    _self.videoEle.addEventListener("canplaythrough",_self.canplaythrough);
	    let material = Cesium.Material.fromType('Image');
	    material.uniforms.image =_self.videoEle;
	    return material;
	}
	else if(('0'== _self.model.videoType && _self.model.videoUrl ) || 
			('1'== _self.model.videoType && ( _self.model.videoUrl  ||  _self.model.videoId ) ) ){
		_self.videoEle=_self.createVideoEle();
		_self.isCreateVideoEle=true;
		_self.canplaythrough=function () {
	    	_self.viewer.clock.onTick.addEventListener(_self.activeVideoListener, _self);
	    };
	    _self.videoEle.addEventListener("canplaythrough",_self.canplaythrough );
	    let material = Cesium.Material.fromType('Image');
	    material.uniforms.image =_self.videoEle;
	    return material;
	}
	
	
	else{
		if(_self.model.thumbnail){
			return new Cesium.Material({ 
				fabric : {
	     		    type : 'Image',
	     		    uniforms : {
	     		      image : _self.model.thumbnail
	     		    }
	     		}
	  		})
		}else{
			return new Cesium.Material({
			    fabric : {
			        type : 'Color',
			        uniforms : {
			            color : Cesium.Color.BLACK.withAlpha(0.5)
			        }
			    }
			})
		}
	}
};

VFG.CalculatorBillboard.prototype.createVideoEle = function () {
	var _self = this;
	 var r = document.createElement("VIDEO");
	var src;
	if('0'==_self.model.videoType){
		src=_self.model.videoUrl;
	}
	else{
    	_self.webRtcServer= new WebRtcStreamer(r,_self.model.webRTCUrl);
	    _self.webRtcServer.connect(_self.model.videoId,'','');
	}
	this.videoId = "visualDomId"+_self.option.id;
    var t = document.createElement("SOURCE");
    t.type = "video/mp4",
    t.src = src;
    var i = document.createElement("SOURCE");
    i.type = "video/quicktime",
    i.src = src;
    return r.setAttribute("autoplay", !0),
    r.setAttribute("loop", !0),
    r.setAttribute("crossorigin", !0),
    r.setAttribute("muted", "muted"),
    r.appendChild(t),
    r.appendChild(i),
    r.style.display = "none",
    document.body.appendChild(r),
    r
}

VFG.CalculatorBillboard.prototype.getMatrix = function() {
	var _this = this;
	var modelMatrix = Cesium.Transforms.eastNorthUpToFixedFrame(Cesium.Cartesian3.fromDegrees(this.position.x*1, this.position.y*1,this.position.z*1));
	var scaleMatrix = Cesium.Matrix4.fromScale(new Cesium.Cartesian3(_this.model.scaleX?_this.model.scaleX*1:1,_this.model.scaleY?_this.model.scaleY*1:1,_this.model.scaleZ?_this.model.scaleZ*1:1));
		modelMatrix = Cesium.Matrix4.multiply(modelMatrix, scaleMatrix, new Cesium.Matrix4());
		var hprRotation = Cesium.Matrix3.fromHeadingPitchRoll(new Cesium.HeadingPitchRoll(
				Cesium.Math.toRadians(this.orientation.heading || 0), 
				Cesium.Math.toRadians(this.orientation.pitch || 0), 
				Cesium.Math.toRadians(this.orientation.roll || 0)));
	var hpr = Cesium.Matrix4.fromRotationTranslation(hprRotation,new Cesium.Cartesian3(0.0, 0.0, 0.0));
	return Cesium.Matrix4.multiply(modelMatrix, hpr, modelMatrix);
}; 

VFG.CalculatorBillboard.prototype.activeVideoListener = function (e) {
	var _this=this;
    try {
        if (_this._videoPlay && _this.videoEle.paused) _this.videoEle.play();
    } catch (e) {}
}

VFG.CalculatorBillboard.prototype.deActiveVideo = function (e) {
	this.viewer.clock.onTick.removeEventListener(this.activeVideoListener, this);
}


VFG.CalculatorBillboard.prototype.update=function(param){
	if(param.position){
		this.position=param.position;
	}
	if(param.orientation){
		if(this.orientation.pitch){
			this.orientation.pitch=param.orientation.pitch;
		}
		if(this.orientation.heading){
			this.orientation.heading=param.orientation.heading;
		}
		if(this.orientation.roll){
			this.orientation.roll=param.orientation.roll;
		}
	}
	if(param.scale){
		if(this.scale.x){
			this.model.scaleX=param.scale.x;
		}
		if(this.scale.y){
			this.model.scaleY=param.scale.y;
		}
		if(this.scale.z){
			this.model.scaleZ=param.scale.z;
		}
	}
	if(this.primitive){
		this.primitive.modelMatrix=this.getMatrix();
	}
}

VFG.TModel.prototype.updateThing=function(thing){
	if(thing){
	}
}

VFG.CalculatorBillboard.prototype.addListener=function(type,callback){
	if('success'==type){
		this.success=callback;
	}
	if('error'==type){
		this.error=callback;
	}
	if('complete'==type){
		this.complete=callback;
	}
}

VFG.CalculatorBillboard.prototype.removeListener=function(type){
	if('beforeSend'==type){
		this.beforeSend=null;
	}
	if('success'==type){
		this.success=null;
	}
	if('error'==type){
		this.error=null;
	}
	if('complete'==type){
		this.complete=null;
	}
}

VFG.CalculatorBillboard.prototype.destroy = function () {
  this.deActiveVideo();
  if(this.primitive){
	  this.viewer.scene.primitives.remove(this.primitive);
  }
  if(this.primitive){
	  this.viewer.scene.primitives.remove(this.primitive);
  }
  if(this.videoEle){
	  this.videoEle.removeEventListener('canplaythrough',this.canplaythrough);
  }
  if(this.webRtcServer){
	  this.webRtcServer.disconnect();
  }
  if(this.isCreateVideoEle){
	  this.videoEle && this.videoEle.parentNode.removeChild(this.videoEle);
  }
  delete this.webRtcServer,
  delete this.videoEle,
  delete this.options,
  delete this.model,
  delete this.primitive,
  delete this.viewer;
  return Cesium.destroyObject(this);
};

/*************************************obj模型解析*******************************************/
VFG.CalculatorBillboard.prototype.parse=function( text ) {
	var _this=this;
	if ( text.indexOf( '\r\n' ) !== - 1 ) {
		text = text.replace( /\r\n/g, '\n' );
	}

	if ( text.indexOf( '\\\n' ) !== - 1 ) {
		text = text.replace( /\\\n/g, '' );
	}

	var lines = text.split( '\n' );
	var line = '', lineFirstChar = '';
	var lineLength = 0;
	var result = [];

	// Faster to just trim left side of the line. Use if available.
	var trimLeft = ( typeof ''.trimLeft === 'function' );

	for ( var i = 0, l = lines.length; i < l; i ++ ) {

		line = lines[ i ];
		line = trimLeft ? line.trimLeft() : line.trim();
		lineLength = line.length;
		if ( lineLength === 0 ) continue;

		lineFirstChar = line.charAt( 0 );
		// @todo invoke passed in handler if any
		if ( lineFirstChar === '#' ) continue;

		if ( lineFirstChar === 'v' ) {
			var data = line.split( /\s+/ );
			switch ( data[ 0 ] ) {
				case 'v':
					_this.vertices.push(
						parseFloat( data[ 1 ] ),
						parseFloat( data[ 2 ] ),
						parseFloat( data[ 3 ] )
					);
					if ( data.length >= 7 ) {
						_this.colors.push(
							parseFloat( data[ 4 ] ),
							parseFloat( data[ 5 ] ),
							parseFloat( data[ 6 ] )
						);
					} else {
						_this.colors.push( undefined, undefined, undefined );
					}
					break;
				case 'vn':
					_this.normals.push(
						parseFloat( data[ 1 ] ),
						parseFloat( data[ 2 ] ),
						parseFloat( data[ 3 ] )
					);
					break;
				case 'vt':
					_this.uvs.push(
						parseFloat( data[ 1 ] ),
						parseFloat( data[ 2 ] )
					);
					break;

			}

		} else if ( lineFirstChar === 'f' ) {
			var lineData = line.substr( 1 ).trim();
			var vertexData = lineData.split( /\s+/ );
			var faceVertices = [];

			// Parse the face vertex data into an easy to work with format
			for ( var j = 0, jl = vertexData.length; j < jl; j ++ ) {
				var vertex = vertexData[ j ];
				if ( vertex.length > 0 ) {
					var vertexParts = vertex.split( '/' );
					faceVertices.push( vertexParts );
					this.geometry.indices.push(vertexParts[0]*1-1);
				}
				
			}
			var v1 = faceVertices[ 0 ];
			for ( var j = 1, jl = faceVertices.length - 1; j < jl; j ++ ) {
				var v2 = faceVertices[ j ];
				var v3 = faceVertices[ j + 1 ];
				_this.addFace(
					v1[ 0 ], v2[ 0 ], v3[ 0 ],
					v1[ 1 ], v2[ 1 ], v3[ 1 ],
					v1[ 2 ], v2[ 2 ], v3[ 2 ]
				);
			}
		} else {
			if ( line === '\0' ) continue;
		}
	}
}

VFG.CalculatorBillboard.prototype.addFace= function ( a, b, c, ua, ub, uc, na, nb, nc ) {
	var vLen = this.vertices.length;
	
	var ia = this.parseVertexIndex( a, vLen );
	var ib = this.parseVertexIndex( b, vLen );
	var ic = this.parseVertexIndex( c, vLen );

	this.addVertex( ia, ib, ic );
	this.addColor( ia, ib, ic );
	
	
	 this.geometry.indices.push(ia);
	 this.geometry.indices.push(ib);
	 this.geometry.indices.push(ic);
	

	// normals
	if ( na !== undefined && na !== '' ) {
		var nLen = this.normals.length;
		ia = this.parseNormalIndex( na, nLen );
		ib = this.parseNormalIndex( nb, nLen );
		ic = this.parseNormalIndex( nc, nLen );
		this.addNormal( ia, ib, ic );
	} else {
		this.addFaceNormal( ia, ib, ic );
	}

	// uvs
	if ( ua !== undefined && ua !== '' ) {
		var uvLen = this.uvs.length;
		ia = this.parseUVIndex( ua, uvLen );
		ib = this.parseUVIndex( ub, uvLen );
		ic = this.parseUVIndex( uc, uvLen );
		this.addUV( ia, ib, ic );
	} else {
		this.addDefaultUV();
	}
}

//use
VFG.CalculatorBillboard.prototype.addVertex=function ( a, b, c ) {
	var src = this.vertices;
	var dst = this.geometry.vertices;
	dst.push( src[ a + 0 ], src[ a + 1 ], src[ a + 2 ] );
	dst.push( src[ b + 0 ], src[ b + 1 ], src[ b + 2 ] );
	dst.push( src[ c + 0 ], src[ c + 1 ], src[ c + 2 ] );
}

//use
VFG.CalculatorBillboard.prototype.addNormal=function ( a, b, c ) {
	var src = this.normals;
	var dst = this.geometry.normals;
	dst.push( src[ a + 0 ], src[ a + 1 ], src[ a + 2 ] );
	dst.push( src[ b + 0 ], src[ b + 1 ], src[ b + 2 ] );
	dst.push( src[ c + 0 ], src[ c + 1 ], src[ c + 2 ] );
}

//use
VFG.CalculatorBillboard.prototype.addFaceNormal=function ( a, b, c ) {

	var src = this.vertices;
	var dst = this.geometry.normals;

	vA.fromArray( src, a );
	vB.fromArray( src, b );
	vC.fromArray( src, c );

	cb.subVectors( vC, vB );
	ab.subVectors( vA, vB );
	cb.cross( ab );

	cb.normalize();

	dst.push( cb.x, cb.y, cb.z );
	dst.push( cb.x, cb.y, cb.z );
	dst.push( cb.x, cb.y, cb.z );

}

//use
VFG.CalculatorBillboard.prototype.addColor= function ( a, b, c ) {

	var src = this.colors;
	var dst = this.geometry.colors;

	if ( src[ a ] !== undefined ) dst.push( src[ a + 0 ], src[ a + 1 ], src[ a + 2 ] );
	if ( src[ b ] !== undefined ) dst.push( src[ b + 0 ], src[ b + 1 ], src[ b + 2 ] );
	if ( src[ c ] !== undefined ) dst.push( src[ c + 0 ], src[ c + 1 ], src[ c + 2 ] );

}

//use
VFG.CalculatorBillboard.prototype.addUV= function ( a, b, c ) {
	var src = this.uvs;
	var dst = this.geometry.uvs;
	dst.push( src[ a + 0 ], src[ a + 1 ] );
	dst.push( src[ b + 0 ], src[ b + 1 ] );
	dst.push( src[ c + 0 ], src[ c + 1 ] );
}

//use
VFG.CalculatorBillboard.prototype.addDefaultUV=function () {
	var dst = this.geometry.uvs;
	dst.push( 0, 0 );
	dst.push( 0, 0 );
	dst.push( 0, 0 );
}

VFG.CalculatorBillboard.prototype.parseVertexIndex=function ( value, len ) {
	var index = parseInt( value, 10 );
	return ( index >= 0 ? index - 1 : index + len / 3 ) * 3;
}

VFG.CalculatorBillboard.prototype.parseNormalIndex=function ( value, len ) {
	var index = parseInt( value, 10 );
	return ( index >= 0 ? index - 1 : index + len / 3 ) * 3;
}
VFG.CalculatorBillboard.prototype.parseUVIndex=function ( value, len ) {
	var index = parseInt( value, 10 );
	return ( index >= 0 ? index - 1 : index + len / 2 ) * 2;
}


